#include "mainwindow.h"
#include <QSharedMemory>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QFileDialog>
#include <QPixmap>
#include <QBuffer>
#include <QDataStream>
#include <QDebug>
#include <QHBoxLayout>

const char* KEY_SHARED_MEMORY = "Shared";

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    /* 为共享内存对象指定key值 */
    , sharedMemory(new QSharedMemory(KEY_SHARED_MEMORY, this))
{
    QWidget *mainWidget = new QWidget(this);
    QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget);
    setCentralWidget(mainWidget);

    QHBoxLayout *topLayout = new QHBoxLayout;
    QPushButton *saveBtn = new QPushButton(tr("save"), this);
    topLayout->addWidget(saveBtn);
    QPushButton *loadBtn = new QPushButton(tr("load"), this);
    topLayout->addWidget(loadBtn);
    mainLayout->addLayout(topLayout);

    QLabel *picLabel = new QLabel(this);
    mainLayout->addWidget(picLabel);

    // 指定saveButton的槽函数
    connect(saveBtn, &QPushButton::clicked, [=](){
        // 如果sharedMemory已经和某个进程连接，则先断开
        if (sharedMemory->isAttached()){
            sharedMemory->detach();
        }
        //读取图片到DataStream, 并设置到标签上
        QString fileName = QFileDialog::getOpenFileName(this);
        QPixmap pixMap(fileName);
        picLabel->setPixmap(pixMap);
        QBuffer buffer;
        QDataStream out(&buffer);
        buffer.open(QBuffer::ReadWrite);
        out << pixMap;

        int size = buffer.size();
        //请求系统创建共享内存段， 指定创建大小
        if (!sharedMemory->create(size)){
            qDebug() << tr("Create error, ") << sharedMemory->errorString();
        }else{
            // 读取或者写入共享内存时， 需要对其加锁
            sharedMemory->lock();
            // 获取共享内存段的地址
            char *to = static_cast<char*>(sharedMemory->data());
            const char* from = buffer.data().constData();
            // 把数据拷贝到共享内存段
            memcpy(to, from, qMin(size, sharedMemory->size()));
            // 之后， 解锁共享内存段
            sharedMemory->unlock();
        }
    });

    // loadButton的槽函数
    connect(loadBtn, &QPushButton::clicked, [=](){
        // 将当前进程或线程附着到共享内存
        if (!sharedMemory->attach()){
            qDebug() << tr("Attach error: ") << sharedMemory->errorString();
        }else{
            QBuffer buffer;
            QDataStream in(&buffer);
            QPixmap pixMap;
            sharedMemory->lock();
            // 将共享内存段的数据读取到buffer中
            buffer.setData(static_cast<const char*>(sharedMemory->constData()),
                           sharedMemory->size());
            // buffer内容写入到pixMap
            buffer.open(QBuffer::ReadWrite);
            in >> pixMap;
            // 解锁
            sharedMemory->unlock();
            // 把当前进程从共享内存中分离开
            sharedMemory->detach();
            // 图片显示在标签上
            picLabel->setPixmap(pixMap);
        }
    });
}

MainWindow::~MainWindow()
{

}

